<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <!-- Set -->
    <script>
        // 类似数组, 但成员值唯一
        // 两个NaN - 相等, 两个对象 - 不等
        const s = new Set([1]);
        [2, 2, 3, 4, 4, 4, 5].forEach(x => s.add(x));
        console.log(s); // {size: 5, 1, 2, 3, 4, 5}
        // 利用该特性可以实现数组去重/字符串去重
        const arr = [1, 2, 2, 3, 4, 4, 4, 4];
        const arrNew = [...new Set(arr)];
        const str = 'hahahayes';
        const strNew = [...new Set('str')].join('');
        console.log(arrNew, strNew);

        // keys(), values(), entries()
        let keys = [], values = [], entries = [];
        // keys()&values()行为完全一致
        for (let item of s.keys()) {
            keys.push(item);
        }
        for (let item of s.values()) {
            values.push(item);
        }
        // entries()返回按照插入顺序产生的包含两个元素的数组, 两个元素都是出现的值
        for (let item of s.entries()) {
            entries.push(item);
        }
        console.log(entries, keys, values); // entries - [1, 1], [2, 2], [3, 3], [4, 4], [5, 5]
        // values()为默认迭代器, 集合实例可以直接引用, 转化为数组
        console.log([...s]);

        // forEach() - 对每个元素执行操作, 第二个参数指定this值, 没有返回值
        s.forEach((value) => console.log(value + 2));
        // 由于forEach没有返回值, 如果想同步改变原来的Set结构, 可以使用如下方法
        // 1 - 映射出新结构赋值
        let set1 = new Set([1, 2, 3]);
        set1 = new Set([...set1].map(val => val * 2));
        // 2 - 利用Array.from
        let set2 = new Set([1, 2, 3]);
        set2 = new Set(Array.from(set2, val => val * 2));
        console.log(set1, set2);

        // 应用 - 求并集, 交集, 差集 (结合数组的map和filter方法)
        let a = new Set([1, 2, 3]);
        let b = new Set([4, 3, 2]);
        // 并集
        let union = new Set([...a, ...b]);
        // 交集
        let intersect = new Set([...a].filter(x => b.has(x)));
        // （a 相对于 b 的）差集
        let difference = new Set([...a].filter(x => !b.has(x)));
        console.log(union, intersect, difference);
    </script>

    <!-- WeakSet -->
    <script>
        let ws = new WeakSet([{id: 1}, {id: 2}, {id: 3}]);
        // WeakSet中的集合只能是Object或继承自Object的类型（null除外）
        // WeakSet不可遍历, 垃圾回收机制不考虑弱【集合】所引用的对象
        // 三个实例方法 - add() delete() has()
        ws.add([4]);
        // ws.add(4); // 报错
        console.log(ws);
    </script>
</body>

</html>